// test_arm64_syscalls.go
package main

import (
    "fmt"
    "os"
    "runtime"
    "syscall"
)

const (
    // ARM64 syscall numbers
    SYS_MMAP_ARM64   = 222
    SYS_MUNMAP_ARM64 = 215
    SYS_MREMAP_ARM64 = 216
    
    // x86_64 syscall numbers
    SYS_MMAP_X86     = 9
    SYS_MUNMAP_X86   = 11
    SYS_MREMAP_X86   = 25
    
    MAP_HUGETLB      = 0x40000
    MAP_HUGE_2MB     = (21 << 26)
    MAP_PRIVATE      = 0x2
    MAP_ANONYMOUS    = 0x20
    MAP_FIXED        = 0x10
    PROT_READ        = 0x1
    PROT_WRITE       = 0x2
    PROT_EXEC        = 0x4
)

func getSyscallNumbers() (mmap, munmap, mremap uintptr) {
    if runtime.GOARCH == "arm64" {
        return SYS_MMAP_ARM64, SYS_MUNMAP_ARM64, SYS_MREMAP_ARM64
    }
    return SYS_MMAP_X86, SYS_MUNMAP_X86, SYS_MREMAP_X86
}

func testMmap() {
    mmapSyscall, _, _ := getSyscallNumbers()
    
    fmt.Printf("Testing mmap on %s architecture\n", runtime.GOARCH)
    
    // Test regular mmap
    addr, _, errno := syscall.Syscall6(
        mmapSyscall,
        0,                        // addr
        4096,                     // length
        PROT_READ|PROT_WRITE,     // prot
        MAP_PRIVATE|MAP_ANONYMOUS, // flags
        0,                        // fd
        0,                        // offset
    )
    
    if errno != 0 {
        fmt.Printf("Regular mmap failed: %v (errno: %d)\n", errno, int(errno))
    } else {
        fmt.Printf("Regular mmap succeeded: address 0x%x\n", addr)
        // Test munmap
        _, _, errno := syscall.Syscall(
            mmapSyscall+3, // munmap syscall (typically mmap_syscall + 3 for x86, but different for ARM)
            addr,
            4096,
            0,
        )
        if errno != 0 {
            fmt.Printf("Regular munmap failed: %v (errno: %d)\n", errno, int(errno))
        } else {
            fmt.Printf("Regular munmap succeeded\n")
        }
    }
    
    // Test huge page mmap (if supported)
    addr, _, errno = syscall.Syscall6(
        mmapSyscall,
        0,                                   // addr
        2*1024*1024,                         // length (2MB)
        PROT_READ|PROT_WRITE,                // prot
        MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|MAP_HUGE_2MB, // flags
        0,                                   // fd
        0,                                   // offset
    )
    
    if errno != 0 {
        fmt.Printf("Huge page mmap failed: %v (errno: %d)\n", errno, int(errno))
        // This is likely where you're getting -22 (EINVAL)
    } else {
        fmt.Printf("Huge page mmap succeeded: address 0x%x\n", addr)
        // Test munmap
        _, _, errno := syscall.Syscall(
            mmapSyscall+3,
            addr,
            2*1024*1024,
            0,
        )
        if errno != 0 {
            fmt.Printf("Huge page munmap failed: %v (errno: %d)\n", errno, int(errno))
        } else {
            fmt.Printf("Huge page munmap succeeded\n")
        }
    }
}

func main() {
    if len(os.Args) > 1 && os.Args[1] == "test" {
        testMmap()
        return
    }
    
    // Simple program to be traced by tiexec
    fmt.Println("Hello from test program!")
    
    // Allocate some memory to make the test more interesting
    data := make([]byte, 1024*1024) // 1MB
    for i := range data {
        data[i] = byte(i % 256)
    }
    
    sum := 0
    for _, v := range data {
        sum += int(v)
    }
    
    fmt.Printf("Sum of data: %d\n", sum)
}